package step_2.players.play_ahead;

import step_2.checkers_board.Board;
import step_2.checkers_board.CheckersMove;
import step_2.players.Player;

public class PlayAhead implements Player {

	final int nMovesAhead;
	public PlayAhead(int iMovesAhead) {
		nMovesAhead = iMovesAhead*2;
	}

	@Override
	public CheckersMove getMove(Board board) {

		Board tempBoard = new Board(board);
		CheckersMove move= setupBestMove(tempBoard,nMovesAhead);
		return move;
	}

	private CheckersMove selectBestMove(Board board, int movesAhead) {
		final CheckersMove[] legalMoves = board.getLegalMoves();
		final int nMoves = legalMoves.length;
		CheckersMove bestMove = legalMoves[0];
		int bestScore = board.scoreMove(bestMove);
		if (nMoves>0 && movesAhead>0) {
			for (int iMove = 1; iMove < nMoves; iMove++) {
				Board boardCopy = new Board(board);
				CheckersMove nextMove = legalMoves[iMove];
				boardCopy.doMakeMove(nextMove);
				int score = boardCopy.scoreMove(selectBestMove(boardCopy, movesAhead-1));
				if (score > bestScore) {
					score = bestScore;
					bestMove = legalMoves[iMove];
				}
			}

		} 
		return bestMove;
	}

	/**
	 * bestMove = function(Board board, piece piece, int lookAhead)
{
 possibleMoves = getPossibleMoves(board, piece)
 bestMove = null
 bestScore = -INFINITY
 boardCp = clone(board)     

 for (move in possibleMoves)
 {
    // just the original code
     if(lookAhead <= 1) {
         tempBoard = applyMove(boardCp, move)
         if (tempBoard.score > bestScore)
         {
             bestMove = move
             bestScore = tempBoard.score
          }
         boardCp = undoMove(tempBoard, move)
     }

     // recursion, can be changed to a loop 
     else {
        tempBoard = applyMove(boardCp, move)                // apply
        move2 = bestMove(tempBoard, piece, lookAhead-1)     // dive and get best 
        boardCp = undoMove(tempBoard, move)                 // (1) check how good it actually is
        tempBoard = applyMove(boardCp, move2)
        if (tempBoard.score > bestScore)
         {
             bestMove = move2
             bestScore = tempBoard.score
          }
        boardCp = undoMove(tempBoard, move2)                // generaly I'd refactor both if-else paths and reuse some code
     }
  }


return bestMove
}    
	 * @param board
	 * @param lookAhead
	 * @return
	 */
	private CheckersMove setupBestMove(Board board, int lookAhead)
	{
		CheckersMove bestMove = this.bestMove(board, lookAhead);
		return bestMove;
	}
	private CheckersMove bestMove(Board board, int lookAhead)
	{
		final CheckersMove[] possibleMoves = board.getLegalMoves();
		 Board boardCp = new Board(board);     
			CheckersMove bestMove;
			int bestScore;
			bestMove = null;
			bestScore = Integer.MIN_VALUE;

		for (CheckersMove move: possibleMoves)
		{
			/* just the original code */
			Board tempBoard = new Board(boardCp);
			if(lookAhead <= 2) {
				int score = tempBoard.scoreMove(move);
				if (score > bestScore) {
					bestScore = score;
					bestMove = move;
				}
			}

			/* recursion, can be changed to a loop */
			else {
				tempBoard.doMakeMove(move);
				CheckersMove move2 = bestMove(tempBoard, lookAhead-1);     // dive and get best 
				int score = tempBoard.scoreMove(move2);
				if (score > bestScore) {
					score = bestScore;
					bestMove = move2;
				}
			}
		}

		return bestMove;
	}    

}
